package contegor.scire.structure.lang;

import java.util.List;
import java.util.concurrent.ExecutionException;

import contegor.scire.core.Attribute;
import contegor.scire.core.Concept;
import contegor.scire.core.queries.Filter;
import contegor.scire.core.queries.Query;
import contegor.scire.structure.Context;

/** Holds a meaning group data. */
public final class MeaningGroupData {
  private Query<Concept> query = null;
  private Attribute attribute = null;
  private boolean againstContext = true;

  /**
   * If the {@link MeaningGroupData} refers to {@link Concept} instances, this is the {@link Query}
   * that will retrieve them.
   */
  public Query<Concept> getQuery() {
    return query;
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  public void setQuery(Query query) throws UnderstandException {
    this.query = query;
  }

  /** Returns current query filtered with current attribute, if there is one. */
  public Query<Concept> getQueryFilteredWithAttribute() {
    if (attribute != null)
      return new Filter<Concept>(attribute.createConditionInstance(), this.query);
    else
      return this.query;
  }

  /**
   * If the meaning group to which this {@link MeaningGroupData} belongs has an {@link Attribute},
   * it will be stored here.
   */
  public Attribute getAttribute() {
    return attribute;
  }

  public void setAttribute(Attribute attribute) throws UnderstandException {
    if (this.attribute != null)
      throw new UnderstandException("Attribute already set. Old one: " + this.attribute);
    this.attribute = attribute;
  }

  /**
   * Set to true if the {@link Query} set in {@link #setQuery(Query)} must be submitted to the {@link Context}.
   * False if it must be submitted to the {@link Context}'s cloud.
   */
  public void setAgainstContext(boolean againstContext) {
    this.againstContext = againstContext;
  }

  /** Gets {@link Concept}s referred by current {@link #query} and {@link #condition}. */
  public List<Concept> retreive(Context ctx) throws InterruptedException, ExecutionException {
    Query<Concept> aux;
    if (attribute != null)
      aux = new Filter<Concept>(attribute.createConditionInstance(), this.query);
    else
      aux = this.query;
    if (this.againstContext)
      return ctx.process(aux).get();
    else
      return ctx.pull(aux);
  }
}